package me.zhengjie.common;

import com.google.common.collect.Lists;
import java.lang.reflect.ParameterizedType;
import java.util.Date;
import java.util.Set;
import javax.annotation.PostConstruct;
import me.zhengjie.base.BaseEntity;
import me.zhengjie.utils.SecurityUtils;
import org.beetl.sql.core.SQLManager;
import org.beetl.sql.core.db.MetadataManager;
import org.beetl.sql.core.db.TableDesc;
import org.beetl.sql.core.mapper.BaseMapper;
import org.springframework.beans.factory.annotation.Autowired;

public abstract class BaseService<T extends BaseEntity, I> {

  @Autowired
  private BaseMapper<T> baseMapper;

  private Class<T> clazz;

  @PostConstruct
  private void init() {
    Object obj = this.getClass().getGenericSuperclass();
    if (obj instanceof ParameterizedType) {
      ParameterizedType type = (ParameterizedType) obj;
      clazz = (Class<T>) type.getActualTypeArguments()[0];
    } else {
      clazz = (Class<T>) obj;
    }
  }

  private void prePersist(T clazz) {
    if (clazz.getCreateTime() == null) {
      clazz.setCreateTime(new Date());
    }
    clazz.setCreateBy(SecurityUtils.getCurrentUsername());
  }

  private void preUpdate(T clazz) {
    clazz.setUpdateTime(new Date());
    clazz.setUpdatedBy(SecurityUtils.getCurrentUsername());
  }

  public T findOne(I id) {
    return baseMapper.unique(id);
  }

  private String getPrimaryKey() {
    SQLManager sm = baseMapper.getSQLManager();
    MetadataManager mm = sm.getDbStyle().getMetadataManager();
    TableDesc table = mm.getTable(sm.getNc().getTableName(clazz));
    Set<String> idNames = table.getIdNames();
    if (idNames.size() > 1) {
      throw new RuntimeException("暂不支持复合主键的查询！");
    }
    return idNames.iterator().next();
  }

  public void insertTemplate(T clazz) {
    prePersist(clazz);
    baseMapper.insertTemplate(clazz);
  }

  public T insertTemplate(T clazz, boolean autDbAssignKey) {
    prePersist(clazz);
    baseMapper.insertTemplate(clazz, autDbAssignKey);
    return clazz;
  }

  public T updateById(T clazz) {
    preUpdate(clazz);
    baseMapper.updateById(clazz);
    return clazz;
  }

  public void delete(Long[] ids) {
    if (ids.length == 0) {
      return;
    }
    baseMapper.createLambdaQuery().andIn(getPrimaryKey(), Lists.newArrayList(ids)).delete();
  }
}
